题意简述
给一个长度为 $n$ 的序列 $a_1,a_2…a_n$,求两个区间 $[l_1,r_1],[l_2,r_2]$,使得两端区间不相交,且两端区间的异或和加起来最大。
$n\le 10^5$,每个 $a_i\le 10^9$。
思路
设 $s_i$ 为前缀 $i$ 个的异或和。那么 $[l,r]$ 的异或和相当于 $s_r\oplus s_{l-1}$($\oplus$ 表示异或)。
设 $pre[i]$ 表示在 $[1,i]$ 中区间的异或和的最大值。$suf[i]$ 表示 $[i,n]$ 中区间的异或和的最大值。那么答案就是 $max\{pre[i]+suf[i+1]\},1\le i\le n-1$。
然后 $pre$ 和 $suf$ 求法基本相同,如果会求 $pre$,只要反过来求一遍就能求出 $suf$ 了。
然后我们可以用 01-TRIE
求出必须以 $i$ 为右端点的最大区间异或和。然后求一个前缀最大值,就能得到 $pre$ 数组了。
如何求(会的跳过)
假设我们当前有一些数。我们把它二进制拆分成 $32$ 位,然后从高到低插入 TRIE
树中。
现在我们要查询,这些数中哪个和 $x$ 异或起来最大。
我们把 $x$ 也拆开,对于当前这一位 $x[i]$(其值为 $0/1$),如果有一个儿子编号和 $x[i]$ 不同,尽量往不同的这里走,并且答案加上 $2^i$。否则就只能走相同的那一条边了,因为相同的异或起来为 $0$,所以这时对答案没有贡献。
我们把 $s[0,1,2\cdots i-1]$ 都插入到 TRIE
树中,然后查询必须选 $s[i]$ 的答案,就能得到以 $i$ 为右端点的最大区间异或和。然后求一遍前缀最大值,就能得到 $pre$ 数组。
代码
1 |
|